using System;
using System.Collections.Generic;
using System.Text;

namespace ImagesMath.Transformations
{
    public class Scaling : Transformation
    {


        public Scaling(ref VR3 scale): base(new M33(),scale)
        {
            L.VX.X    = scale.X;
            L.VY.Y = scale.Y;      
            L.VZ.Z = scale.Z;
            invL.VX.X = 1 / scale.X; 
            invL.VY.Y = 1 / scale.Y; 
            invL.VZ.Z = 1 / scale.Z;
        }


        public Scaling(double scaleX, double scaleY, double scaleZ)
            
        {
            this.t = new VR3(0, 0, 0);

            L.VX.X    = scaleX;
            L.VY.Y =    scaleY;      
            L.VZ.Z =    scaleZ;
            invL.VX.X = 1 / scaleX; 
            invL.VY.Y = 1/scaleY; 
            invL.VZ.Z = 1/scaleZ;
        }

        public VR3  GetScale()
        {
            return new VR3(L.VX.X, L.VY.Y, L.VZ.Z);
        }
        public void SetScale(ref VR3 scale)
        {
            L.VX.X = scale.X;
            L.VY.Y = scale.Y;
            L.VZ.Z = scale.Z;
            invL.VX.X = 1 / scale.X;
            invL.VY.Y = 1 / scale.Y;
            invL.VZ.Z = 1 / scale.Z;
        }
        public void SetScale(double scaleX,double scaleY,double scaleZ)
        {
            L.VX.X = scaleX;
            L.VY.Y = scaleY;
            L.VZ.Z = scaleZ;
            invL.VX.X = 1 / scaleX;
            invL.VY.Y = 1 / scaleY;
            invL.VZ.Z = 1 / scaleZ;
        }



        #region Functions

        /// Compute the concatenation of (*this) and Tr [ (*this)*Tr ]
        public virtual Transformation rightMultiply(Transformation Tr)
        {
            return new Transformation(new M33(Tr.L.VX.X * L.VX.X, Tr.L.VX.Y * L.VY.Y, Tr.L.VX.Z * L.VZ.Z,
              Tr.L.VY.X * L.VX.X, Tr.L.VY.Y * L.VY.Y, Tr.L.VY.Z * L.VZ.Z,
              Tr.L.VZ.X * L.VX.X, Tr.L.VZ.Y * L.VY.Y, Tr.L.VZ.Z * L.VZ.Z,true),

              new VR3(Tr.T.X * L.VX.X, Tr.T.Y * L.VY.Y, Tr.T.Z * L.VZ.Z),

              new M33(Tr.InvL.VX * invL.VX.X, Tr.InvL.VY * invL.VY.Y, Tr.InvL.VZ * invL.VZ.Z,true),

              Tr.InvT);
            
        }
        /// Compute the concatenation of Tr and (*this) [ Tr*(*this) ]
        public virtual Transformation leftMultiply(Transformation Tr)
        {
            return new Transformation(new M33(Tr.L.VX * L.VX.X, Tr.L.VY * L.VY.Y, Tr.L.VZ * L.VZ.Z,true),

              Tr.T,

              new M33(Tr.InvL.VX.X * invL.VX.X, Tr.InvL.VX.Y * invL.VY.Y, Tr.InvL.VX.Z * invL.VZ.Z,
              Tr.InvL.VY.X * invL.VX.X, Tr.InvL.VY.Y * invL.VY.Y, Tr.InvL.VY.Z * invL.VZ.Z,
              Tr.InvL.VZ.X * invL.VX.X, Tr.InvL.VZ.Y * invL.VY.Y, Tr.InvL.VZ.Z * invL.VZ.Z,true),

              new VR3(Tr.InvT.X * invL.VX.X, Tr.InvT.Y * invL.VY.Y, Tr.InvT.Z * invL.VZ.Z));
            
        }
        public virtual PR3 transform(PR3 p)
        {
            return new PR3(p.X * L.VX.X, p.Y * L.VY.Y, p.Z * L.VZ.Z);
        }
        public virtual PR3 invTransform(PR3 p)
        {
            return new PR3(p.X * invL.VX.X, p.Y * invL.VY.Y, p.Z * invL.VZ.Z);
        }
        public virtual VR3 transform(VR3 v)
        {
            return new VR3(v.X * L.VX.X, v.Y * L.VY.Y, v.Z * L.VZ.Z);
        }
        public virtual VR3 invTransform(VR3 v)
        {
            return new VR3(v.X * invL.VX.X, v.Y * invL.VY.Y, v.Z * invL.VZ.Z);
        }

        #endregion



        ///// Compute the concatenation of (*this) and Tr [ (*this)*Tr ]
        //      Transform rightMultiply(const Transform& Tr) const;
        ///// Compute the concatenation of Tr and (*this) [ Tr*(*this) ]
        //      Transform leftMultiply (const Transform& Tr) const;
        //      pR3       transform    (const pR3& p) const;
        //      pR3       invTransform (const pR3& p) const;
        //      vR3       transform    (const vR3& v) const;
        //      vR3       invTransform (const vR3& v) const;
        //  };
        //
// Scaling interface
//










//Transform Scaling::rightMultiply(const Transform& Tr) const
//{
//  return Transform(m33(Tr.L.vx.x * L.vx.x, Tr.L.vx.y * L.vy.y ,Tr.L.vx.z * L.vz.z,
//    Tr.L.vy.x * L.vx.x, Tr.L.vy.y * L.vy.y, Tr.L.vy.z * L.vz.z,
//    Tr.L.vz.x * L.vx.x, Tr.L.vz.y * L.vy.y, Tr.L.vz.z * L.vz.z),

//    vR3(Tr.T.x * L.vx.x, Tr.T.y * L.vy.y, Tr.T.z * L.vz.z),

//    m33(Tr.InvL.vx * invL.vx.x, Tr.InvL.vy * invL.vy.y, Tr.InvL.vz * invL.vz.z),

//    Tr.invT);
//}


//Transform Scaling::leftMultiply(const Transform& Tr) const
//{
//  return Transform(m33(Tr.L.vx * L.vx.x, Tr.L.vy * L.vy.y, Tr.L.vz * L.vz.z),

//    Tr.T,

//    m33(Tr.InvL.vx.x * invL.vx.x, Tr.InvL.vx.y * invL.vy.y, Tr.InvL.vx.z * invL.vz.z,
//    Tr.InvL.vy.x * invL.vx.x, Tr.InvL.vy.y * invL.vy.y, Tr.InvL.vy.z * invL.vz.z,
//    Tr.InvL.vz.x * invL.vx.x, Tr.InvL.vz.y * invL.vy.y, Tr.InvL.vz.z * invL.vz.z),

//    vR3(Tr.invT.x * invL.vx.x, Tr.invT.y * invL.vy.y, Tr.invT.z * invL.vz.z));
//}


//pR3 Scaling::transform(const pR3& p) const
//{
//  return pR3(p.x*L.vx.x,p.y*L.vy.y,p.z*L.vz.z);
//}


//pR3 Scaling::invTransform(const pR3& p) const
//{
//  return pR3(p.x*invL.vx.x,p.y*invL.vy.y,p.z*invL.vz.z);
//}


//vR3 Scaling::transform(const vR3& v) const
//{
//  return vR3(v.x*L.vx.x,v.y*L.vy.y,v.z*L.vz.z);
//}


//vR3 Scaling::invTransform(const vR3& v) const
//{
//  return vR3(v.x*invL.vx.x,v.y*invL.vy.y,v.z*invL.vz.z);
//}


    }
}
